package 算法复习课.手动造轮子.list;


import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.concurrent.CountDownLatch;

/**
 * @author linhao
 * @date created in 10:24 下午 2020/10/19
 */
public class ArrayList<T> implements List<T> {

    private Object[] arr;
    private int size;
    private int current;
    private static final int DEFAULT_SIZE = 10;
    private static final float ENLARGE_ARR_THREADSOLD = 0.75f;
    private static final float ENLARGE_ARR_NUMBER = 1.5f;
    /**
     * fast-fail
     */
    private volatile int modCount;
    private volatile int exceptModCount;

    public ArrayList() {
        new ArrayList(DEFAULT_SIZE);
    }

    public ArrayList(int capacity) {
        this.current = 0;
        this.size = capacity;
        arr = new Object[capacity];
    }


    @Override
    public T add(T t) {
        grow();
        arr[current] = t;
        current++;
        modCount++;
        return t;
    }

    @Override
    public void set(int index, T data) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("index is illegal");
        }
        modCount++;
        arr[index] = data;
    }

    @Override
    public T remove(int index) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("index is illegal");
        }
        Object temp = arr[index];
        modCount++;
        arr[index] = null;
        current--;
        return (T) temp;
    }

    @Override
    public int indexOf(T data) {
        if (data == null) {
            throw new IllegalArgumentException("data can not be null");
        }
        for (int i = 0; i < arr.length; i++) {
            if (data.equals((T) arr[i])) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public boolean contain(T data) {
        return indexOf(data) >= 0;
    }

    @Override
    public T get(int index) {
        if (index < 0 || index > size) {
            throw new IllegalArgumentException("illegal index");
        }
        return (T) arr[index];
    }

    @Override
    public void grow() {
        int threadHold = (int) (ENLARGE_ARR_THREADSOLD * size);
        if (current >= threadHold) {
            size = (int) (ENLARGE_ARR_NUMBER * size);
            arr = Arrays.copyOf(arr, size);
        }
    }

    @Override
    public boolean isEmpty() {
        return size <= 0;
    }

    @Override
    public void display() {
        for (Object o : arr) {
            System.out.print(o + " ");
        }
        System.out.println();
    }

    @Override
    public Iterator<T> iterator() {
        if (current != size) {
            Itr itr = new Itr();
            itr.cursor = 0;
            itr.lastRet = 0;
            return itr;
        }
        return null;
    }

    @Override
    public boolean ensureListSafe() {
        return modCount == exceptModCount;
    }

    private class Itr implements Iterator {

        int cursor;
        int lastRet;

        public Itr() {
            exceptModCount = modCount;
        }

        @Override
        public boolean hasNext() {
            return cursor < size && arr[cursor] != null;
        }


        @Override
        public Object next() {
            if (!ensureListSafe()) {
                throw new ConcurrentModificationException("current time has over 2 thread were visit in current List");
            }
            if (cursor > size || cursor == -1) {
                throw new NoSuchElementException("no next element");
            }
            lastRet = cursor;
            cursor = cursor + 1;
            return arr[lastRet];
        }
    }



    public static void test(){
        CountDownLatch countDownLatch = new CountDownLatch(1);
        List<Integer> arrayList = new ArrayList(10);
        for (int i = 0; i < 10; i++) {
            arrayList.add(i);
        }
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                int finalI = i;
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        arrayList.add(finalI * 10);
                    }
                });
                t.start();
            } else {
                Thread t = new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            countDownLatch.await();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Iterator iterator = arrayList.iterator();
                        while (iterator.hasNext()) {
                            System.out.println(iterator.next());
                        }
                    }
                });
                t.start();
            }

        }
        countDownLatch.countDown();
        System.out.println("所有线程执行完毕");
        Thread.yield();
    }

    public static void useArrayInMethod(String[] arr){
        if(arr ==null || arr.length==0){
            return;
        } else{
            String[] tempArr = new String[arr.length];
            tempArr = Arrays.copyOf(arr,arr.length);
            tempArr[0]="idea";
            System.out.println("函数里面修改了arr");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        java.util.List<Integer> list = Arrays.asList(1,2,3,4,5);

        String[] paramArr = new String[]{"1","2"};
        useArrayInMethod(paramArr);
        //由于原始数组的引用对象也被篡改了数值，所以这里的paramArr本身也会发生改变
        System.out.println(Arrays.toString(paramArr));
    }
}
